<?php
/**
 * Created by PhpStorm.
 * User: DaibiDaddy
 * Date: 2016/5/24
 * Time: 17:14
 */
namespace App\Base;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\PersistentCollection;
use Symfony\Component\Inflector\Inflector;

class IRI
{

    public static $base = "/api_/";

    public static function isString($value){
        return (string)$value;
    }
    public static function isInt($value){
        return (int)$value;
    }
    public static function isFloat($value){
        return (float)$value;
    }
    public static function isDateTime($value){

        if ($value  instanceof \DateTime){
            $dateTime =  $value;
        }else{
            $dateTime = new \DateTime();
            $dateTime->setTimestamp(strtotime($value));
        }
        return $dateTime->format(YYMMDDHHIISS);
    }
    public static function isArray($value){
        if (is_array($value)) {
            return $value;
        }else{
            return $value = json_decode($value,true);
        }
    }

    public static function create($class,$attribute,$value)
    {
        if ($attribute == "id" && $value) {return (int)$value;}
        if ($attribute == "id" && !$value) {return null;}
        if ($value === null) {return null;}
        $ref = new \ReflectionClass($class);
//        dd($ref);
        $findMethod["set"] = "set".ucfirst($attribute);
        $findMethod["add"][] = "add".ucfirst($attribute);
        if (is_array($try =Inflector::singularize($attribute) )) {
            foreach ($try as $name) {
                $findMethod["add"][] = "add".ucfirst($name);
            }
        }else{
            $findMethod["add"][] = "add".ucfirst($try);
        }

        $funcType = "";
        $func = "";
        if (method_exists($class,$findMethod["set"])) {
            $funcType = "set";
            $func = $findMethod["set"];
        }
        foreach ($findMethod["add"] as $funcName) {
            if (method_exists($class,$funcName)) {
                $funcType = "add";
                $func = $funcName;
            }
        }

        if (!$funcType && !$func) {
//            dd([$findMethod]);
//            throw  new \Exception("未找到相应方法,[$attribute]",500);
            return null;
        }

//        try {
//            $method = $ref->getMethod("set".ucfirst($attribute));
//        } catch (\Exception $exception) {
//            try {
//                $method = $ref->getMethod("add".ucfirst($attribute));
//            } catch (\Exception $exception) {
//
//
//                $method = $ref->getMethod("add".ucfirst(Inflector::singularize($attribute)));
//            }
//
//        }
        if ($funcType == "set") {
            $method = $ref->getMethod($func);
//            dump($method->getParameters());
            //单数
            $type = $method->getParameters()[0]->getType();
            return self::createSingle($type,$value,$class);
        }else{
            $method = $ref->getMethod($func);
            //add 复数
            $type = $method->getParameters()[0]->getType();
            return self::createMany($type,$value,$class);
        }
    }

    public static function createSingle(\ReflectionNamedType $type, $value,$class = "")
    {
        switch ($type) {
            case "string":
                return self::isString($value);
            case "float":
                return self::isFloat($value);
            case "int":
                return self::isInt($value);
            case "bool":
                return $value?true:false;
            case "array":
                return self::isArray($value);
            case "DateTimeInterface":
                return self::isDateTime($value);
            case "self":
                return self::createIRIStringFromEntity($class,$value);
            default:
                if (substr($type->getName(),0,3 ) != "App") {
                    //发现未考虑到的类型
                    throw new \Exception("this is a new type:".$type->getName(),500);
                }else{
                    return self::createIRIStringFromEntity($type->getName(),$value);
                }
        }
    }
    public static function createMany(\ReflectionNamedType $type, $value,$class = "")
    {
        if (!is_array($value)){$value = [$value];}
        $re = array();
        foreach ($value as $val){
            $re[] = self::createSingle($type,$val,$class);
        }
        return $re;

    }

    public static function createIRIStringFromEntity($entityName,$value){
        if (!$value) {return null;}
        if (!is_int($value)) {return $value;}
        $tmpArray = explode("\\",$entityName);
        $txt = end($tmpArray);
        $txt = lcfirst($txt);
        $txt = Inflector::pluralize($txt);
        $txt = preg_replace("/([A-Z])/","_$1",$txt);
        $txt = strtolower($txt);
        return self::$base.$txt."/".$value;
    }

    public static function toArray($entity){
        $ref = new \ReflectionClass($entity);
        $class = $ref->getName();
        $attributes = $ref->getProperties();
//        dump($entity);
//        dump($attributes);
        $array = [];
        foreach ($attributes as $attr) {
            if ($attr->getName() == "id") {
                $array[$attr->getName()] =$entity->getId();
            }else{
                $func = "get".ucfirst($attr->getName());
                $val = $entity->$func();
//                dump($val);

                if (is_object($val) && !($val  instanceof \DateTime)){
                    if ($val instanceOf ArrayCollection  || $val instanceof  PersistentCollection  || $val instanceof  Collection) {
                        $array[$attr->getName()] = array();
                        /**@var $val ArrayCollection */
                        $sons = $val->getValues();
//                        dump($sons);
                        $ids = [];
                        foreach ($sons as $son) {
                            $ids[] = $son->getId();
                        }
                        if ($sons == []) {
                            $array[$attr->getName()] = [];
                        }else{
                            $array[$attr->getName()] = self::create($class,$attr->getName(),$ids);
                        }

                    }else{
                        $array[$attr->getName()] = self::create($class,$attr->getName(),$val->getId());

                    }
                }else if($val  instanceof \DateTime){
                    $array[$attr->getName()] = $val->format(YYMMDDHHIISS);
                }else{
                    $array[$attr->getName()] = self::create($class,$attr->getName(),$val);
                }
            }
        }
        return $array;
    }
}
